package com.sjc.counter.demo;

import com.google.gson.Gson;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.util.Collections.max;

/**
 * @Classname Metrics
 * @Description 最小原型
 * recordResponseTime() 函数用来记录接口请求的响应时间
 * recordTimestamp() 函数用来记录接口请求的访问时间。
 * startRepeatedReport() 函数以指定的频率统计数据并输出结果。
 * @Date 2020/5/1 11:24
 * @Created by SangJiacun
 */
public class Metrics {
    //Map 的key是接口名称， value是接口请求的响应时间或时间戳
    private Map<String, List<Double>> responseTimes = new HashMap<>();
    private Map<String, List<Double>> timestamps = new HashMap<>();

    private ScheduledExecutorService executor  = Executors.newSingleThreadScheduledExecutor();

    public void recordResponseTime(String apiName,double responseTime){
        //putIfAbsent: 如果key存在，则不覆盖。如果不存在，则存入key,value
        responseTimes.putIfAbsent(apiName,new ArrayList<>());
        responseTimes.get(apiName).add(responseTime);
    }

    public void recordTimestamp(String apiName, double timestamp){
        timestamps.putIfAbsent(apiName,new ArrayList<>());
        timestamps.get(apiName).add(timestamp);
    }

    public void startRepeatedReport(long period, TimeUnit unit){
        // 每间隔一段时间定时执行任务
        // scheduleWithFixedDelay(Runnable command,long initialDelay,long period,TimeUnit unit)
        //      以上一次任务的结束时间为间隔。
        // scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
        //      以上一次任务的开始时间为间隔。当任务执行时间 大于 间隔时间，真正间隔的时间 = 任务执行时间。
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                Gson gson = new Gson();
                Map<String, Map<String,Double>> stats = new HashMap<>();
                for(Map.Entry<String,List<Double>> entry : responseTimes.entrySet()){
                    String apiName = entry.getKey();
                    List<Double> apiRespTimes = entry.getValue();
                    stats.putIfAbsent(apiName,new HashMap<>());
                    stats.get(apiName).put("max",max(apiRespTimes));
                    stats.get(apiName).put("avg",avg(apiRespTimes));
                }

                for(Map.Entry<String,List<Double>> entry : timestamps.entrySet()){
                    String apiName = entry.getKey();
                    List<Double> apiTimestamps = entry.getValue();
                    stats.putIfAbsent(apiName,new HashMap<>());
                    stats.get(apiName).put("count",(double)apiTimestamps.size());
                }
                System.out.println(gson.toJson(stats));

            }
        },0,period,unit);
    }

    private double max(List<Double> dataset){
        return Collections.max(dataset);
    }

    private double avg(List<Double> dataset){
//        dataset.stream().mapToDouble(Double :: doubleValue).average().orElse(0D);
        return dataset.stream().collect(Collectors.averagingDouble(Double :: doubleValue));
    }
}
